#include "pngtextureloader.h"
#include "resource/texture.h"
#include "core/File.h"
#include <png.h>

using namespace kraw;

PNGTextureLoader::PNGTextureLoader(const std::string& name) :
png_ptr(NULL),
info_ptr(NULL),
data(NULL),
byte(0)
{
	assetName = name;
}

PNGTextureLoader::~PNGTextureLoader()
{
	if (png_ptr)
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
	}
}

void PNGAPI user_read_data_fcn(png_structp png_ptr, png_bytep data, png_size_t length)
{
	PNGTextureLoader* in = (PNGTextureLoader*)png_ptr->io_ptr;
	memcpy(data, &in->data[in->byte], length);

	in->byte += length;
}

bool PNGTextureLoader::load()
{
	Texture* texture = static_cast<Texture*>(resource);
	if (texture == NULL)
		return false;

	if (!loadBuffer())
		return false;

	
	data = buffer;

	//load info
	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
		NULL, NULL, NULL);

	if (png_ptr == NULL) {
		return false;
	}

	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL) {
		png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
		return false;
	}

	if (setjmp(png_jmpbuf(png_ptr))) {
		png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
		return false;
	}

	// load info
	png_set_read_fn(png_ptr, this, user_read_data_fcn); // Set our read function

	int png_transforms = 0;
	png_set_palette_to_rgb(png_ptr);
	png_read_info(png_ptr, info_ptr);

	texture->textureWidth = png_get_image_width(png_ptr, info_ptr);
	texture->textureHeight = png_get_image_height(png_ptr, info_ptr);
	int color_type = png_get_color_type(png_ptr, info_ptr);
	int bit_depth = png_get_bit_depth(png_ptr, info_ptr);

	texture->pixelFormat = PixelFormat_RGBA8888;
	switch (color_type)
	{
	case PNG_COLOR_TYPE_RGBA: texture->pixelFormat = PixelFormat_RGBA8888; break;
	case PNG_COLOR_TYPE_RGB: texture->pixelFormat = PixelFormat_RGB565; break;
	case PNG_COLOR_TYPE_GRAY: texture->pixelFormat = PixelFormat_A8; break;
	case PNG_COLOR_TYPE_PALETTE:
		{
			texture->pixelFormat = info_ptr->num_trans == 0 ? PixelFormat_RGB565 : PixelFormat_RGBA8888;
		}
	}

	// load data
	png_read_update_info(png_ptr, info_ptr);
	png_bytepp row_pointers;
	row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * texture->textureHeight);

	int channels = 0;
	switch (texture->pixelFormat)
	{
		case GL_RGBA: channels = 4; break;
		case GL_RGB: channels = 3; break;
		case GL_ALPHA: channels = 1; break;
	}
	int rowbytes = texture->textureWidth * channels;

	return true;

	unloadBuffer();
	data = NULL;

	return true;
}

void PNGTextureLoader::unload()
{
	if (png_ptr)
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		info_ptr = NULL;
		png_ptr = NULL;
	}
}
